unit PacketData;

interface

uses
  Classes, Windows, {$ifdef debug}siAuto,{$endif}SysUtils;

Type
  TPacketData = Class
    private
      FStream, FStreamTmp: TMemoryStream;
      procedure Clear;
      function GetData: pointer;
      function GetSize: int64;
    public
      function Add(Command:integer; Data:Pointer; Size:int64): TMemoryStream; overload;
      function Add(Command:integer; Data:AnsiString): TMemoryStream; overload;
      function Add(Command:integer; Data:integer): TMemoryStream; overload;

      procedure Get(Src:TMemoryStream; var Data: pointer; var Size:int64; var Command:integer); OVERLOAD;
      procedure Get(Src:TMemoryStream; var Data: pointer; var Size:int64); overload;
      procedure ParseData(Var Data:Pointer; var size:int64; var Command:integer);

      Constructor Create;
      Destructor  Destroy; override;

      property Stream:TMemoryStream read FStream;
      property Data:pointer         read GetData;
      property Size:int64           read GetSize;
  End;

//----------------------------------------------------------------------------
// Utility Functions.
//----------------------------------------------------------------------------
Function StreamToString(Stream:TMemoryStream):String;
Function PointToString(var Data: Pointer; Size: int64):String;

implementation

Function PointToString(var Data: Pointer; Size: int64):String;
var
  Stream: TMemoryStream;
  buff:AnsiString;
begin
  Result := '';
  Stream := TMemoryStream.Create;
  try
    if not Assigned(Data) then Exit;
    Stream.Write(Data^, Size);
    Stream.Position := 0;

    SetLength(Buff, Size);
    Stream.Read(pointer(Buff)^, Size);
    Result := Buff;
  finally
    Stream.Free;
  end;
end;

Function StreamToString(Stream:TMemoryStream):String;
var
  sStream: TStringStream;
begin
  stream.Position := 0;
  sStream := TStringStream.Create;
  try
    sStream.LoadFromStream(Stream);
    Result := stream.ToString;
  finally
    sStream.Free;
  end;
end;

{ TPacketData }


function TPacketData.Add(Command: integer; Data: Pointer;
  Size: int64): TMemoryStream;
begin
  self.Clear;
  FStream.Write(Command, Sizeof(Command));
  if Data <> nil then
  begin
    FStream.Write(Data^, Size);
  end;
  FStream.Position := 0;
  Result := FStream;
end;

function TPacketData.Add(Command: integer; Data: AnsiString): TMemoryStream;
begin
  self.Clear;
  FStream.Write(Command, Sizeof(Command));
  FStream.Write(Data[1], Length(Data));

  FStream.Position := 0;
  {$ifdef debug}
    //siMain.LogStream('TPacketData.Added Stream', FStream);
  {$endif}
  Result := FStream;
end;

function TPacketData.Add(Command, Data: integer): TMemoryStream;
begin
  self.Clear;
  FStream.Write(Command, Sizeof(Command));
  FStream.Write(Data, Sizeof(Data));
  FStream.Position := 0;
  Result := FStream;
end;

procedure TPacketData.Clear;
begin
  FStream.Clear;
end;

constructor TPacketData.Create;
begin
  FStream    := TMemoryStream.Create;
  FStreamTmp := TMemoryStream.Create;

end;

destructor TPacketData.Destroy;
begin
  FreeAndNil( FStream );
  FreeAndNil( FStreamTmp );
  inherited;
end;

procedure TPacketData.ParseData(var Data: Pointer; var size: int64;
  var Command: integer);
begin
  Self.Get( FStream, Data, Size, Command );
end;

procedure TPacketData.Get(Src:TMemoryStream; var Data: pointer; var Size:int64; var Command:integer);
begin
  Data := nil;
  self.clear;
  size := 0;

  if src.Size = 0 then Exit;

  src.Position := 0;
  src.Read(Command, sizeof(integer));

  if src.Position < src.Size then
  begin
    Size := src.Size - sizeof(integer);
    GetMem(Data, Size);
    Windows.ZeroMemory(Data, Size);
    src.Read(Data^, Size);
  end;
end;


procedure TPacketData.Get(Src: TMemoryStream; var Data: pointer;
  var Size: int64);
begin
  Data := nil;
  self.clear;
  size := 0;

  if src.Size = 0 then Exit;

  src.Position := 0;

  if src.Position < src.Size then
  begin
    Size := src.Size;
    GetMem(Data, Size);
    Windows.ZeroMemory(Data, Size);
    src.Read(Data^, Size);
  end;
end;

function TPacketData.GetData: pointer;
begin
  Result := FStream.Memory;
end;

function TPacketData.GetSize: int64;
begin
  Result := FStream.Size;
end;


end.
